package handler

import (
	"bufio"
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"

	"gitee.com/li-zhenyi/yi-nian-zhi-jian/backend/internal/service"
	"github.com/gin-gonic/gin"
)

// AdventureHandler 历练处理器
// 处理历练相关的HTTP请求
type AdventureHandler struct {
	adventureService service.AdventureService
	cozeAPIKey       string
	cozeBotID        string
}

// NewAdventureHandler 创建历练处理器实例
func NewAdventureHandler(adventureService service.AdventureService, cozeAPIKey, cozeBotID string) *AdventureHandler {
	return &AdventureHandler{
		adventureService: adventureService,
		cozeAPIKey:       cozeAPIKey,
		cozeBotID:        cozeBotID,
	}
}

// StartAdventure 开始新的历练（已废弃，请使用 StreamAdventure）
// POST /api/v1/game/adventure/start
// 注意：此接口已改为调用流式接口，建议前端直接使用 /stream
// Deprecated: 请使用 StreamAdventure 获得更好的用户体验
func (h *AdventureHandler) StartAdventure(c *gin.Context) {
	// 返回提示信息，建议使用流式接口
	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "请使用流式接口 POST /api/v1/game/adventure/stream 以获得更好的体验",
		"data": gin.H{
			"redirect": "/api/v1/game/adventure/stream",
			"note":     "流式接口支持实时展示AI生成过程，提升用户体验",
		},
	})
}

// MakeChoice 做出选择（已废弃，请使用 StreamAdventure）
// POST /api/v1/game/adventure/choice
// 注意：此接口已改为调用流式接口，建议前端直接使用 /stream
// Deprecated: 请使用 StreamAdventure 并传递 conversation_id 继续对话
func (h *AdventureHandler) MakeChoice(c *gin.Context) {
	// 返回提示信息，建议使用流式接口
	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "请使用流式接口 POST /api/v1/game/adventure/stream 以获得更好的体验",
		"data": gin.H{
			"redirect": "/api/v1/game/adventure/stream",
			"note":     "流式接口支持实时展示AI生成过程，并自动管理会话上下文",
			"usage":    "请在请求体中传递 conversation_id 和用户选择内容",
		},
	})
}

// GetHistory 获取历练历史
// GET /api/v1/game/adventure/history
func (h *AdventureHandler) GetHistory(c *gin.Context) {
	// 获取查询参数
	limitStr := c.DefaultQuery("limit", "10")
	limit, err := strconv.Atoi(limitStr)
	if err != nil || limit <= 0 {
		limit = 10
	}

	// TODO: 从JWT token中获取用户ID
	userID := int64(1)

	// 调用Service层获取历史记录
	records, err := h.adventureService.GetAdventureHistory(userID, limit)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取历史记录失败",
			"error":   err.Error(),
		})
		return
	}

	// 返回成功响应
	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "success",
		"data":    records,
	})
}

// GetStats 获取历练统计
// GET /api/v1/game/adventure/stats
func (h *AdventureHandler) GetStats(c *gin.Context) {
	// TODO: 从JWT token中获取用户ID
	userID := int64(1)

	// 调用Service层获取统计信息
	stats, err := h.adventureService.GetAdventureStats(userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取统计信息失败",
			"error":   err.Error(),
		})
		return
	}

	// 返回成功响应
	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "success",
		"data":    stats,
	})
}

// StreamAdventure 流式历练接口
// POST /api/v1/game/adventure/stream
// 使用SSE实时推送Coze AI生成的历练故事和选项
// 流式结束后，异步落地奖励到数据库
func (h *AdventureHandler) StreamAdventure(c *gin.Context) {
	// 请求体结构
	type StreamRequest struct {
		ConversationID string                   `json:"conversation_id"` // 会话ID，首次可为空
		UserID         string                   `json:"user_id"`
		Messages       []map[string]interface{} `json:"additional_messages"`
		Parameters     map[string]interface{}   `json:"parameters"`
	}

	var req StreamRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "参数错误: " + err.Error()})
		return
	}

	// 构造Coze API URL
	cozeURL := "https://api.coze.cn/v3/chat"
	if req.ConversationID != "" {
		cozeURL += "?conversation_id=" + req.ConversationID
	}

	// 构造请求体
	payload, err := json.Marshal(map[string]interface{}{
		"bot_id":              h.cozeBotID,
		"user_id":             req.UserID,
		"stream":              true,
		"additional_messages": req.Messages,
		"parameters":          req.Parameters,
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "构造请求失败"})
		return
	}

	// 创建HTTP请求
	httpReq, err := http.NewRequestWithContext(context.Background(), "POST", cozeURL, bytes.NewReader(payload))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建请求失败"})
		return
	}

	httpReq.Header.Set("Authorization", "Bearer "+h.cozeAPIKey)
	httpReq.Header.Set("Content-Type", "application/json")

	// 发起请求
	resp, err := http.DefaultClient.Do(httpReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Coze API请求失败: " + err.Error()})
		return
	}
	defer resp.Body.Close()

	// 设置SSE响应头
	c.Writer.Header().Set("Content-Type", "text/event-stream")
	c.Writer.Header().Set("Cache-Control", "no-cache")
	c.Writer.Header().Set("Connection", "keep-alive")
	c.Writer.Header().Set("Access-Control-Allow-Origin", "*")

	// 用于收集完整响应的变量
	var (
		conversationID string // 会话ID
		lastEventType  string // 最后一个事件类型
		messageData    []byte // 最后一条消息的完整数据
	)

	// 逐行读取并转发Coze流式响应
	scanner := bufio.NewScanner(resp.Body)
	for scanner.Scan() {
		line := scanner.Text()

		// Coze返回格式: event: xxx 和 data: {...}
		if strings.HasPrefix(line, "event:") {
			lastEventType = strings.TrimSpace(line[6:]) // 去掉 "event:" 前缀
			// 直接转发给前端
			fmt.Fprintf(c.Writer, "%s\n", line)
			c.Writer.Flush()
		} else if strings.HasPrefix(line, "data:") {
			dataContent := strings.TrimSpace(line[5:]) // 去掉 "data:" 前缀

			// 直接转发给前端
			fmt.Fprintf(c.Writer, "%s\n", line)
			c.Writer.Flush()

			// 收集数据用于后续处理
			if dataContent != "" && dataContent != "[DONE]" {
				// 尝试解析 JSON
				var data map[string]interface{}
				if err := json.Unmarshal([]byte(dataContent), &data); err == nil {
					// 提取 conversation_id
					if convID, ok := data["conversation_id"].(string); ok && convID != "" {
						conversationID = convID
					}

					// 只保存 type="answer" 且 event="conversation.message.completed" 的消息
					// 这是包含完整故事和奖励信息的消息
					if lastEventType == "conversation.message.completed" {
						if msgType, ok := data["type"].(string); ok && msgType == "answer" {
							messageData = []byte(dataContent)
							fmt.Printf("[SSE] 保存answer消息用于游戏数据解析: id=%v\n", data["id"])
						}
					}
				}
			}
		}
	}

	if err := scanner.Err(); err != nil && err != io.EOF {
		fmt.Fprintf(c.Writer, "data: {\"error\": \"读取响应失败\"}\n\n")
		c.Writer.Flush()
		return
	}

	// 在流结束前，同步解析并推送游戏数据（story + choices）
	h.sendGameData(c, messageData, conversationID)

	// 流式推送结束后，异步处理奖励落地
	// 使用 goroutine 避免阻塞前端响应
	go h.processAdventureRewards(req.UserID, conversationID, messageData)
}

// processAdventureRewards 处理历练奖励落地
// 在流式推送结束后异步调用，解析AI返回的奖励并更新数据库
func (h *AdventureHandler) processAdventureRewards(userIDStr, conversationID string, messageData []byte) {
	// 解析用户ID
	// TODO: 实际应该从JWT token中获取
	// userID := parseUserID(userIDStr)
	
	// 暂时使用固定ID用于开发测试
	_ = userIDStr // 避免未使用变量警告
	userID := uint(1)

	// 解析最后一条消息数据，提取奖励信息
	if len(messageData) == 0 {
		fmt.Printf("[历练奖励] 无奖励数据: user_id=%d, conversation_id=%s\n", userID, conversationID)
		return
	}

	// 第一步：解析 SSE 消息的外层结构
	var sseMessage struct {
		ID             string `json:"id"`
		ConversationID string `json:"conversation_id"`
		Role           string `json:"role"`
		Type           string `json:"type"`
		Content        string `json:"content"` // 这是一个 JSON 字符串
		ContentType    string `json:"content_type"`
	}

	if err := json.Unmarshal(messageData, &sseMessage); err != nil {
		fmt.Printf("[历练奖励] SSE消息解析失败: %v\n", err)
		return
	}

	// 只处理 type="answer" 的消息（包含故事和奖励）
	if sseMessage.Type != "answer" {
		fmt.Printf("[历练奖励] 跳过非answer类型消息: type=%s\n", sseMessage.Type)
		return
	}

	// 第二步：解析 content 字段（这是一个嵌套的 JSON 字符串）
	var aiResponse struct {
		Result     string `json:"result"` // 故事结果
		Reward     *struct {
			Cultivation int `json:"cultivation"` // 修为奖励
			Items       []struct {
				ID     int    `json:"id"`
				Name   string `json:"name"`
				Type   string `json:"type"`
				Effect string `json:"effect"`
			} `json:"items"` // 物品奖励
			SpiritStones int    `json:"spirit_stones"` // 灵石奖励（如果AI返回的话）
			Exp          string `json:"exp"`           // 经验描述
		} `json:"reward,omitempty"` // 奖励字段可能不存在
		NextBranch *struct {
			HasNext   bool `json:"has_next"`
			NextStory string `json:"next_story"`
			Choices   []struct {
				ID   int    `json:"id"`
				Text string `json:"text"`
			} `json:"choices"`
		} `json:"next_branch,omitempty"` // 下一分支
	}

	// 尝试解析 JSON（AI 可能在 JSON 后面添加了额外的文本说明）
	if err := json.Unmarshal([]byte(sseMessage.Content), &aiResponse); err != nil {
		// 如果失败，尝试提取第一个完整的 JSON 对象
		fmt.Printf("[历练奖励] 直接解析失败，尝试提取 JSON 对象: %v\n", err)
		
		content := sseMessage.Content
		startIdx := strings.Index(content, "{")
		if startIdx == -1 {
			fmt.Printf("[历练奖励] 未找到 JSON 开始标记\n")
			return
		}
		
		// 从 startIdx 开始，找到匹配的右括号
		braceCount := 0
		endIdx := -1
		for i := startIdx; i < len(content); i++ {
			if content[i] == '{' {
				braceCount++
			} else if content[i] == '}' {
				braceCount--
				if braceCount == 0 {
					endIdx = i + 1
					break
				}
			}
		}
		
		if endIdx == -1 {
			fmt.Printf("[历练奖励] 未找到 JSON 结束标记\n")
			return
		}
		
		jsonStr := content[startIdx:endIdx]
		
		if err := json.Unmarshal([]byte(jsonStr), &aiResponse); err != nil {
			fmt.Printf("[历练奖励] 提取后仍然解析失败: content=%s, error=%v\n", jsonStr, err)
			return
		}
	}

	// 如果没有奖励，只记录历练过程
	if aiResponse.Reward == nil {
		fmt.Printf("[历练奖励] 本次历练无奖励: user_id=%d, conversation_id=%s, result=%s\n", 
			userID, conversationID, aiResponse.Result)
		return
	}

	// 第三步：提取奖励数据
	fmt.Printf("[历练奖励] 检测到奖励: user_id=%d, conversation_id=%s\n", userID, conversationID)
	fmt.Printf("  - 修为: +%d\n", aiResponse.Reward.Cultivation)
	fmt.Printf("  - 灵石: +%d\n", aiResponse.Reward.SpiritStones)
	fmt.Printf("  - 物品: %d件\n", len(aiResponse.Reward.Items))
	for _, item := range aiResponse.Reward.Items {
		fmt.Printf("    * %s (ID:%d, 类型:%s, 效果:%s)\n", 
			item.Name, item.ID, item.Type, item.Effect)
	}
	fmt.Printf("  - 经验: %s\n", aiResponse.Reward.Exp)

	// 第四步：调用 Service 层应用奖励
	// 将 Handler 层解析的奖励数据转换为 Service 层所需的格式
	rewardItems := make([]service.RewardItem, 0, len(aiResponse.Reward.Items))
	for _, item := range aiResponse.Reward.Items {
		rewardItems = append(rewardItems, service.RewardItem{
			ID:     item.ID,
			Name:   item.Name,
			Type:   item.Type,
			Effect: item.Effect,
		})
	}

	// 调用 Service 层应用奖励
	err := h.adventureService.ApplyStreamRewards(
		userID,
		conversationID,
		aiResponse.Reward.Cultivation,
		aiResponse.Reward.SpiritStones,
		rewardItems,
	)
	
	if err != nil {
		fmt.Printf("[历练奖励] ❌ 应用奖励失败: %v\n", err)
	} else {
		fmt.Printf("[历练奖励] ✅ 奖励应用成功\n")
	}
}

// sendGameData 解析AI返回的游戏数据并推送给前端
// 在SSE流结束前同步调用，向前端发送完整的游戏数据
// 支持两种格式：
// 1. 首次历练：{ story, choices }
// 2. 选择后：{ result, reward, next_branch: { next_story, choices } }
func (h *AdventureHandler) sendGameData(c *gin.Context, messageData []byte, conversationID string) {
	if len(messageData) == 0 {
		fmt.Printf("[游戏数据] 无消息数据可解析\n")
		return
	}

	// 第一步：解析 SSE 消息的外层结构
	var sseMessage struct {
		Content string `json:"content"` // 这是一个 JSON 字符串
		Type    string `json:"type"`
	}

	if err := json.Unmarshal(messageData, &sseMessage); err != nil {
		fmt.Printf("[游戏数据] SSE消息解析失败: %v\n", err)
		return
	}

	// 只处理 type="answer" 的消息
	if sseMessage.Type != "answer" {
		return
	}

	// 第二步：解析 content 字段（JSON 字符串）
	// 定义完整的AI响应结构（包含所有可能的字段）
	var aiResponse struct {
		// 首次历练字段
		Story   string `json:"story,omitempty"`
		Choices []struct {
			ID            int    `json:"id"`
			Text          string `json:"text"`
			Risk          string `json:"risk,omitempty"`
			RewardPreview string `json:"reward_preview,omitempty"`
		} `json:"choices,omitempty"`
		
		// 选择后字段
		Result string `json:"result,omitempty"`
		Reward *struct {
			Cultivation  int `json:"cultivation"`
			SpiritStones int `json:"spirit_stones,omitempty"`
			Items        []struct {
				ID     int    `json:"id"`
				Name   string `json:"name"`
				Type   string `json:"type"`
				Desc   string `json:"desc,omitempty"`
				Effect string `json:"effect,omitempty"`
			} `json:"items,omitempty"`
		} `json:"reward,omitempty"`
		NextBranch *struct {
			HasNext   bool   `json:"has_next"`
			NextStory string `json:"next_story,omitempty"`
			Choices   []struct {
				ID   int    `json:"id"`
				Text string `json:"text"`
			} `json:"choices,omitempty"`
		} `json:"next_branch,omitempty"`
	}

	// 尝试解析 JSON（AI 可能在 JSON 后面添加了额外的文本说明）
	// 先尝试直接解析
	if err := json.Unmarshal([]byte(sseMessage.Content), &aiResponse); err != nil {
		// 如果失败，尝试提取第一个完整的 JSON 对象
		fmt.Printf("[游戏数据] 直接解析失败，尝试提取 JSON 对象: %v\n", err)
		
		// 查找第一个 '{' 和最后一个匹配的 '}'
		content := sseMessage.Content
		startIdx := strings.Index(content, "{")
		if startIdx == -1 {
			fmt.Printf("[游戏数据] 未找到 JSON 开始标记\n")
			return
		}
		
		// 从 startIdx 开始，找到匹配的右括号
		braceCount := 0
		endIdx := -1
		for i := startIdx; i < len(content); i++ {
			if content[i] == '{' {
				braceCount++
			} else if content[i] == '}' {
				braceCount--
				if braceCount == 0 {
					endIdx = i + 1
					break
				}
			}
		}
		
		if endIdx == -1 {
			fmt.Printf("[游戏数据] 未找到 JSON 结束标记\n")
			return
		}
		
		jsonStr := content[startIdx:endIdx]
		fmt.Printf("[游戏数据] 提取的 JSON: %s\n", jsonStr)
		
		if err := json.Unmarshal([]byte(jsonStr), &aiResponse); err != nil {
			fmt.Printf("[游戏数据] 提取后仍然解析失败: %v\n", err)
			return
		}
	}

	// 构造游戏数据响应（直接转发完整的AI响应结构）
	gameData := map[string]interface{}{
		"conversation_id": conversationID,
	}

	// 添加首次历练字段（如果存在）
	if aiResponse.Story != "" {
		gameData["story"] = aiResponse.Story
		fmt.Printf("[游戏数据] 首次历练模式: story=%d字\n", len(aiResponse.Story))
	}
	if len(aiResponse.Choices) > 0 {
		gameData["choices"] = aiResponse.Choices
	}

	// 添加选择后字段（如果存在）
	if aiResponse.Result != "" {
		gameData["result"] = aiResponse.Result
		fmt.Printf("[游戏数据] 选择后模式: result=%d字\n", len(aiResponse.Result))
	}
	if aiResponse.Reward != nil {
		gameData["reward"] = aiResponse.Reward
		fmt.Printf("[游戏数据] 包含奖励: cultivation=%d, items=%d件\n", 
			aiResponse.Reward.Cultivation, len(aiResponse.Reward.Items))
	}
	if aiResponse.NextBranch != nil {
		gameData["next_branch"] = aiResponse.NextBranch
		if aiResponse.NextBranch.NextStory != "" {
			fmt.Printf("[游戏数据] 包含下一段故事: next_story=%d字\n", len(aiResponse.NextBranch.NextStory))
		}
		fmt.Printf("[游戏数据] 下一分支选项: %d项\n", len(aiResponse.NextBranch.Choices))
	}

	gameDataJSON, err := json.Marshal(gameData)
	if err != nil {
		fmt.Printf("[游戏数据] JSON序列化失败: %v\n", err)
		return
	}

	// 推送自定义事件给前端
	fmt.Fprintf(c.Writer, "event:game.data\n")
	fmt.Fprintf(c.Writer, "data:%s\n\n", string(gameDataJSON))
	c.Writer.Flush()

	fmt.Printf("[游戏数据] ✅ 已推送完整游戏数据\n")
}
